// UPDATED: 3/7/07

#include    <system.h>
#include 	<string.h>
#include    "EESD.h"


/**************************
 * This program contains: *
 *	 1) LCD functions	  *
 *	 2) Serial port fncs  *
 **************************/	


/********************************
 *	ADDED BY CALVIN-Serial port *
 ********************************/

volatile bit txmt @PIR1.4;
volatile bit da @PIR1.5;

//	INITIALIAZE the serial functionality
void serial_init(void)
{
	trise.2 = 0;
	late.2 = 1;
	
	txsta = 00100100b;
	rcsta = 10010000b;
	baudcon = 00001000b;
	
	spbrgh = 0;
	spbrg = 42;
	return;
}

//	Write char to serial port
void putc(char a)
{
	while(txmt==0);
	txreg = a;
	return;
}
//	Read char from serial port
char getc(void)
{
	char a;
	while(!da);
	a = rcreg;
	putc(a);
	return(a);
}

//	Write string to serial port
void putstring(const char* text )
{
  char i = 0;
  while( text[i] != 0 )
    putc( text[i++] );
  return;
}

//	Write decimal value (from short)
void putdec(unsigned short dat)
{
  unsigned short val;   // ascii results
  unsigned short temp;
  unsigned short div;
  unsigned short data;
  char i;
  char digit;
  data = dat;  // make it unsigned
  div = 10000;
  for(i=0; i <= 4; ++i)   // get all 5 digits
  {
    val = data/div;       // get most signif. digit
    putc(val + '0');    // print digit
    data -= val * div;   // what we’ve printed
    div=div/10;         // adjust divisor
  }
  return;
}

//	Read decimal value from serial port
unsigned short getdec(void)
{
	short val;
	unsigned short out;
	char i;
	
	out = 0;
	
	for(i=0; i <= 4; ++i)
	{	
		val = getc();
		out = out + val*(i^10);
		i++;
	}
	return out;
}

/********************************
 * Write char in HEX - format *
 ********************************/
void puthex(char data)
{
  char n;
  n = ((data >> 4) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = (data & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  return;
}

/************************************
 * Write char ARRAY in HEX - format *
 ************************************/
void puthex(char* data)
{
  int length, i;
  char n;
  
  length = strlen(data);
   
  for( i=0; i<=length; i++)
	{
	n = ((data[i] >> 4) & 0x0F) + 0x30;
	if (n > 0x39) n = n+7;
	putc(n);
	n = (data[i] & 0x0F) + 0x30;
	if (n > 0x39) n = n+7;
	putc(n);
	}
  return;
}
/******************************************
 * Write unsigned short in HEX - format *
 ******************************************/
void puthex(unsigned short data)
{
  char n;
  n = ((data >> 12) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 8) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 4) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = (data & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  return;
}
/*****************************************
 * Display unsigned LONG in HEX - format *
 *****************************************/
void puthex(unsigned long data)
{
  char n;
  n = ((data >> 28) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 24) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 20) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 16) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 12) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 8) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 4) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = (data & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  return;
}
/**********************************
 * Display  short in HEX - format *
 **********************************/
void puthex(short data)
{
  char n;
  n = ((data >> 12) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 8) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = ((data >> 4) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  n = (data & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  putc(n);
  return;
}

//	Write unsigned short as a signed int
void putint(short dat)
{
  short val;   // ascii results
  short temp;
  short div;
  char i;
  unsigned short data;
  bool dozero;
  dozero = false;
  data = dat;
  if(dat == 0)  // always print 0
  {
    putc('0');
    return;
  }
  div = 10000;
    /*
     * adjust for sign
     * */
  if(dat < 0)
  {
    putc('-');
    data = ~data + 1;
  }
  for(i=0; i <= 4; ++i)   // get all 3 digits
  {
    val = data/div;       // get most signif. digit
    if(val != 0 || dozero) 
    {
      putc(val + '0');    // print digit
      dozero = true;
    }
    data -= val*div;   	// subtract off what we’ve printed
    div=div/10;         // adjust divisor
  }
}

/**************************************
 *		END ADDED BY CALVIN 		  *
 **************************************/


void LCD_init(void)
{
  trisd = trisd & 0x0f;  //Top 4 pins configured for output
  trise = trise & 0xf8;  //Bottom 3 pins configured for output
  adcon1 |= 0x0f;             // port E digital mode
    
  delay_ms(40);

  LCD_icmd( 0x30 ) ;          /*  8 Bit mode  */
  delay_ms(5);			// DH - min delay here of 4.1 ms
  LCD_icmd( 0x30 ) ;          /*  8 Bit mode  */
  LCD_icmd( 0x30 ) ;          /*  8 Bit mode  */

  LCD_icmd( 0x20 ) ;          /*  4-BIT Mode  */
  LCD_cmd( 0x28 );            /*  Function Set: 4-bit,2-line,5X7 */

  LCD_cmd( 0x0C );            /*  Display on, Cursor off         */
  LCD_cmd( 0x06 );            /*  Entry mode: INC addr, NO SHIFT display */

  LCD_cmd( 0x01 );            /*  Clear Display */
  delay_ms( 20 );
}


/*******************************************************
 *  LCD_cmd - Write ASCII character to LCD peripheral  *
 *      configured as a 4 bit interface                *
 *******************************************************/
void LCD_char(char data)
{
  char dsave;
  dsave = latd;
  LCD_DATA = (data & 0xF0) | (LCD_DATA & 0x0F);         /* Write HI nibble word to LCD */
  write_data;
  LCD_DATA = ((data << 4) & 0xF0) | (LCD_DATA & 0x0F);  /* Write LO nibble word to LCD */
  write_data;
  delay_ms(1);
  latd = dsave;
}
/*****************************************************
 *  LCD_icmd - Write control word to LCD peripheral  *
 *****************************************************/
void LCD_icmd(char data)
{
  char dsave;
  dsave = portd;
  LCD_DATA = data | (LCD_DATA & 0x0F) ;
  write_cmd;

  delay_ms(1);
  portd = dsave;
  return;
}

/***************************************************
 *  LCD_cmd - Write control word to LCD peripheral *
 *      configured as a 4 bit interface            *
 **************************************************/
void LCD_cmd(char data)
{
  char dsave;
  dsave = portd;
  LCD_DATA = (data & 0xF0) | (LCD_DATA & 0x0F);         /* Write HI nibble word to LCD */
  write_cmd;
  LCD_DATA = ((data << 4) & 0xF0) | (LCD_DATA & 0x0F);  /* Write LO nibble word to LCD */
  write_cmd;
  if (data < 0x03) delay_ms(20); else delay_ms(1);
  portd = dsave;
  return;

}
/* set the cursor position */

void LCD_setpos(char line, char pos)
{
  LCD_cmd(0x80 + line * 0x40 + pos);
  return;
}

/**********************
 * routine to clear display screen
 * */
 
void LCD_clear(void)
{
  LCD_cmd( 0x01 );            /*  Clear Display */
  delay_ms(20);
  return;
}

/********************************
 * Display char in HEX - format *
 ********************************/
void LCD_hex(char data)
{
  char n;
  n = ((data >> 4) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  n = (data & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  return;
}
/********************************
 * Display unsigned short in HEX - format *
 ********************************/
void LCD_hex(unsigned short	  data)
{
  char n;
  n = ((data >> 12) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  n = ((data >> 8) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  n = ((data >> 4) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  n = (data & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  return;
}
/********************************
 * Display  short in HEX - format *
 ********************************/
void LCD_hex(short data)
{
  char n;
  n = ((data >> 12) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  n = ((data >> 8) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  n = ((data >> 4) & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  n = (data & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  return;
}
/********************************
 * Display low nibble in HEX - format *
 ********************************/
void LCD_nib(char data)
{
  char n;
  n = (data & 0x0F) + 0x30;
  if (n > 0x39) n = n+7;
  LCD_char(n);
  return;
}

/********************************
 * Display byte in binary - format *
 ********************************/
void LCD_bin(char data)
{
  char n;
  char temp;
  temp =0x80;
  for( n=1; n<=8; ++n)
  {
    if(temp & data)
      LCD_char(0x31);
    else
      LCD_char(0x30);
    temp = temp >> 1;
  }
  return;
}
/********************************
 * Display unsigned short in binary - format *
 ********************************/
void LCD_bin(unsigned short data)
{
  char n;
  unsigned short temp;
  temp =0x8000;
  for( n=1; n<=16; ++n)
  {
    if(temp & data)
      LCD_char(0x31);
    else
      LCD_char(0x30);
    temp = temp >> 1;
  }
}

void LCD_dec(short dat)
{
  unsigned short val;   // ascii results
  unsigned short temp;
  unsigned short div;
  unsigned short data;
  char i;
  char digit;
  data = dat;  // make it unsigned
  div = 10000;
  for(i=0; i <= 4; ++i)   // get all 5 digits
  {
    val = data/div;       // get most signif. digit
    LCD_char(val + '0');    // print digit
    data -= val * div;   // what we’ve printed
    div=div/10;         // adjust divisor
  }
  return;
}

void LCD_dec(unsigned short dat)
{
  unsigned short val;   // ascii results
  unsigned short temp;
  unsigned short div;
  unsigned short data;
  char i;
  char digit;
  data = dat;  // make it unsigned
  div = 10000;
  for(i=0; i <= 4; ++i)   // get all 5 digits
  {
    val = data/div;       // get most signif. digit
    LCD_char(val + '0');    // print digit
    data -= val * div;   // what we’ve printed
    div=div/10;         // adjust divisor
  }
  return;
}
/**********************************
 * Display byte as decimal number *
 **********************************/
void LCD_dec(char data)
{
  LCD_char(((data /100) & 255) + 0x30);
  data = data % 100;
  LCD_char( ((data / 10) & 255) + 0x30 );
  LCD_char( ((data % 10) & 255) + 0x30 );
  return;
}
/*
 * display char as a signed int
 * */

void LCD_int(char data)
{
  char val;   // ascii results
  char temp;
  char div;
  char i;
  bool dozero;
  dozero = false;
  div = 100;
  if(data == 0)  // always print 0
  {
    LCD_char('0');
    return;
  }
    /*
     * adjust for sign
     * */
  if(data & 10000000b)
  {
    LCD_char('-');
    data = ~data + 1;
  }
  for(i=0; i <= 2; ++i)   // get all 3 digits
  {
    val = data/div;       // get most signif. digit
    if(val != 0 || dozero)
    { 
      LCD_char(val + '0');    // print digit
      dozero = true;
    }
    temp = val * div;   // subtract off
    data = data - temp;   // what we’ve printed
    div=div/10;         // adjust divisor
  }
}
/*
 * display unsigned short as a signed int
 * */

void LCD_int(short dat)
{
  short val;   // ascii results
  short temp;
  short div;
  char i;
  unsigned short data;
  bool dozero;
  dozero = false;
  data = dat;
  if(dat == 0)  // always print 0
  {
    LCD_char('0');
    return;
  }
  div = 10000;
    /*
     * adjust for sign
     * */
  if(dat < 0)
  {
    LCD_char('-');
    data = ~data + 1;
  }
  for(i=0; i <= 4; ++i)   // get all 3 digits
  {
    val = data/div;       // get most signif. digit
    if(val != 0 || dozero) 
    {
      LCD_char(val + '0');    // print digit
      dozero = true;
    }
    data -= val*div;   // subtract off what we’ve printed
    div=div/10;         // adjust divisor
  }
}

void LCD_printf( const char* text )
{
  char i = 0;
  while( text[i] != 0 )
    LCD_char( text[i++] );
  return;
}
